home *** CD-ROM | disk | FTP | other *** search
/ PC-X 1997 October / pcx14_9710.iso / swag / delphi.swg / 0075_SetBounds() in DELPHI.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1995-11-24  |  3.3 KB  |  99 lines

  1. {
  2. If you are designing a new Delphi control and you need to catch
  3. or limit changes to Left, Top, Width, or Height, there is one
  4. simple way to do it.  However, I have yet to see the slightest
  5. hint of how to do it in the Delphi documentation (including
  6. the CWG).
  7.  
  8. The key to catching changes to Left, Top, Width, Height, and
  9. even BoundsRect in Delphi is the SetBounds() method (found
  10. in TControl and all descendants).  SetBounds() is a virtual
  11. function used to set the position and size of a control
  12. all in one easy step.  However, what they do not tell you
  13. in the documentation is that TControl.SetBounds() is called
  14. by TControl's SetLeft(), SetTop(), SetWidth(), and SetHeight()
  15. property access methods every time a value is assigned to
  16. the Left, Top, Width, Height, and BoundsRect properties.
  17.  
  18. Thus, to catch changes to these properties, simply override
  19. the SetBounds() method, do whatever you need with the new
  20. values, and then pass them on to the inherited SetBounds()
  21. method.
  22.  
  23. In the following example, I have a control that automatically
  24. updates its X & Y custom properties to refer to the center
  25. of the control whenever Left, Top, Width, Height, or BoundsRect
  26. are changed.  Conversely, Left and Top will be updated whenever
  27. X & Y are changed: }
  28.  
  29. type
  30.   TMyControl = class(TControl)
  31.   private
  32.     FX, FY : integer;
  33.     {property access methods}
  34.     procedure SetX(value : integer);
  35.     procedure SetY(value : integer);
  36.     ...
  37.   public
  38.     procedure SetBounds(aLeft, aTop, aWidth, aHeight : integer); override;
  39.     ...
  40.     property X : integer read FX write SetX;
  41.     property Y : integer read FY write SetY;
  42.   end;
  43. ...
  44.  
  45. procedure TMyControl.SetX(value : integer);
  46. begin
  47.   if FX <> value then 
  48.     SetBounds(value - Width div 2, Top, Width, Height);
  49. end;
  50.  
  51. procedure TMyControl.SetY(value : integer);
  52. begin
  53.   if FY <> value then
  54.     SetBounds(Left, value - Height div 2, Width, Height);
  55. end;
  56.  
  57. procedure TMyControl.SetBounds(aLeft, aTop, aWidth, aHeight : integer);
  58. begin
  59.   {Go ahead and let SetBounds() do its thing...}
  60.   inherited SetBounds(aLeft, aTop, aWidth, aHeight);
  61.   {Now adjust FX and FY according to our new bounds.}
  62.   FX := Width div 2;
  63.   FY := Height div 2;
  64. end;
  65.  
  66. Also not mentioned in the documentation is the fact that the
  67. FLeft, FTop, FWidth, and FHeight private fields that TControl
  68. uses to keep track of its bounding rectangle are not updated
  69. in the corresponding SetLeft(), SetTop(), etc. property access
  70. methods.  These variables, in fact, do not get updated anywhere
  71. except in TControl's SetBounds() method (as with FX and FY in
  72. the above example).
  73.  
  74. So, to limit changes to the bounds of your control, you can
  75. override SetBounds() to check and modify any of the properties
  76. before passing the values on to the inherited SetBounds()
  77. method.
  78.  
  79. In the following example, I have a control that limits its
  80. width and height to no more than 100 pixels:
  81.  
  82. type
  83.   TMyControl = class(TControl)
  84.     ...
  85.   public
  86.     procedure SetBounds(aLeft, aTop, aWidth, aHeight : integer); override;
  87.     ...
  88.   end;
  89.  
  90. ...
  91. procedure TMyControl.SetBounds(aLeft, aTop, aWidth, aHeight : integer);
  92. begin
  93.   if aWidth > 100 then
  94.     aWidth  := 100;
  95.   if aHeight > 100 then
  96.     aHeight := 100;
  97.   inherited SetBounds(aLeft, aTop, aWidth, aHeight);
  98. end;
  99.